#include <stdint.h>
#include "config.h"
#include "apitrans.h"
#include "result.h"
#include "devapi.h"
#include "fcntl.h"

#define CONFIG_PATH    "/appfs/"
#define MAX_SIZE_REC   1000
#define FILE_TYPE_SYSBIN 0X01
#define FILE_TYPE_APPBIN 0X02

static char path[50]={0};
static uint8_t file_type = 0;
static uint8_t sha256_val[32]={0};
static uint8_t fd = 0;
static int last_sn = 0;

static int api_start_receive(unsigned char *cmd, int len)
{
	uint8_t name_len;
	int mod = 0;
	uint32_t ret ;
	uint8_t offset = 0;
	last_sn = -1;
	file_type = cmd[offset];
	offset += 1;
	name_len = cmd[offset];
	offset += 1;
	memcpy(path, CONFIG_PATH ,strlen(CONFIG_PATH));
	memcpy(path + strlen(CONFIG_PATH), cmd + offset, name_len);
	path[name_len+strlen(CONFIG_PATH)]=0;
	offset += name_len;
	memcpy(sha256_val, cmd + offset, 32);
	offset += 32;
	if(offset != len){
		ret = ERROR_PARAM;
		memcpy(cmd, &ret, 2);
		return -1;
	}
	close(fd);
	unlink(path);
	fd = open(path,(O_RDWR|O_CREAT));    
	if(fd < 0){
		ret = FILE_ERR_CODE(fd);
		memcpy(cmd,&ret,2);
		return -1;
	}
	else
		ret = DEAL_SUCCESS;
	
	offset = 0;
	memcpy(cmd,&ret,2);
	offset += 2;
	return offset;
}


static int api_file_receive(unsigned char *cmd, int inlen)
{	
	uint16_t ret = DEAL_SUCCESS;
	char buffer[MAX_SIZE]={0};
	uint16_t offset = 0;
	uint16_t sn=0;
	int len = 0;
	int wlen = 0;
	sn = BCDtoDec(cmd+offset,2);
	offset += 2;
	len = BCDtoDec(cmd+offset,2);
	offset += 2;
	if(len > MAX_SIZE_REC){
		ret = ERROR_PARAM;
		memcpy(cmd, &ret, 2);
		return -1;
	}
	memcpy(buffer, cmd+offset, len);
	offset += len;
	if(offset != inlen){
		ret = ERROR_PARAM;
		goto err;
	}
	if(sn == 0){
		sha2_starts(0);
	}
	if(sn != last_sn){
		last_sn = sn;
		wlen = write(fd,buffer,len);   
		if(len < 0){
			ret = FILE_ERR_CODE(len);
			goto err;
		}
		else if(wlen != len){
			ret = ERR_WRITE;
			goto err;
		}
		sha2_update(buffer, wlen);
		if(cmd[0]==0xff && cmd[1]==0xff){
			sha2_finish(buffer);	
			close(fd);
			ret = 0;
			if (memcmp(buffer, sha256_val, 32) != 0){
				ret = ERR_CHRCK;
				unlink(path);
			}
			offset = 0;
			memcpy(cmd,&ret,2);
			offset +=2;
			cmd[offset++]=0xff;
			cmd[offset++]=0xff;
			
			return offset;
		}
	}
	offset = 0;
	memcpy(cmd,&ret,2);
	offset +=2;
	DectoBCD(sn,cmd+offset,2);
	offset +=2;
	return offset;

err:
	memcpy(cmd,&ret,2);
	close(fd);
	unlink(path);
	return -1;
	
}

static int api_goto_updata(unsigned char *cmd, int len)
{
	uint16_t ret = DEAL_SUCCESS;
	uint8_t offset = 0;
	uint8_t mode = cmd[offset++];
	if(offset != len){
		ret = ERROR_PARAM;
		memcpy(cmd,&ret,2);
		return -1;
	}
	memcpy(cmd,&ret,2);
	if(mode == 0x00){
		return -8;
	}
	else if(mode == 0x01){
		return -9;
	}
}

static func_t recfile_fun[] = {
	NULL, api_start_receive, api_file_receive, api_goto_updata,
};
int cmd_recfile(uint8_t cmd,char *buf, int len)
{
	if(cmd < 0x01 || cmd > sizeof(recfile_fun)/sizeof(recfile_fun[0])) 
		return -5;
	return recfile_fun[cmd](buf,len);
}

